package com.demo.resourcecode.condition;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Configuration1 {

    @Bean
    // 不少人在使用@ConditionalOnBean注解时会遇到不生效的情况，依赖的 bean 明明已经配置了，但就是不生效。到底@ConditionalOnBean和bean加载的顺序有没有关系呢？跟着源码，一探究竟。
    // 结果：
    // @ConditionalOnBean(Bean2.class)返回false。
    // 明明定义了bean2，bean1却未加载。

    // 我们来分析一下上面示例bean1为何没有实例化？

    // 在spring ioc的过程中，优先解析@Component，@Service，@Controller注解的类。其次解析配置类，也就是@Configuration标注的类。最后开始解析配置类中定义的bean。
    // 示例代码中bean1是定义在配置类中的，当执行到配置类解析的时候，@Component，@Service，@Controller ,@Configuration标注的类已经全部被解析，所以这些BeanDifinition已经被同步。
    // 但是bean1的条件注解依赖的是bean2，bean2是被定义的配置类中的，因为两个Bean都是配置类中Bean，所以此时配置类的解析无法保证先后顺序，就会出现不生效的情况。

    // 同样的道理，如果依赖的是FeignClient，也有可能会出现不生效的情况。因为FeignClient最终还是由配置类触发，解析的先后顺序也不能保证。

    // 解决
    // 项目中条件注解依赖的类，大多会交给spring容器管理，所以如果要在配置中Bean通过@ConditionalOnBean依赖配置中的Bean时，完全可以用@ConditionalOnClass(Bean2.class)来代替。
    @ConditionalOnBean(Bean2.class)
    public Bean1 bean1() {
        return new Bean1();
    }

}
